//
//  YLPaymentProcessor.swift
//  YLPaymentKit
//
//  Created by changhe on 2025/4/12.
//

import Foundation
import UIKit

/// 支付类型枚举
public enum YLPaymentType {
    case alipay    // 支付宝
    case wechat    // 微信支付
    case iap       // 内购
}

/// 支付错误枚举
public enum YLPaymentError: Error, Equatable {
    case purchaseInProgress             // 支付进行中
    case purchaseUserCancelled          // 用户取消支付
    case transactionVerificationFailed   // 交易验证失败
    case sdkNotIntegrated(String)       // SDK未集成
    case sdkNotAvailable                // SDK不可用
    case cannotOpenPaymentApp           // 无法打开支付应用
    case missingParameter(String)       // 缺少参数
    case networkError                   // 网络错误
    case unsupportedPaymentType         // 不支持的支付类型
    case invalidParameters              // 参数无效
    case productNotFound                // 未找到商品
    case unknownError                   // 未知错误
    case other(String)                  // 其他错误
    case processorNotFound              // 处理器未找到
    case receiptNotFound                // 收据未找到
    case storeKitError(Error)           // StoreKit错误
    case verifyError(Error)             // 服务器验证失败错误
    
    /// 获取错误码
    public var code: Int {
        switch self {
        case .purchaseInProgress:           return 20001
        case .purchaseUserCancelled:        return 20002
        case .transactionVerificationFailed: return 20003
        case .sdkNotIntegrated:             return 20004
        case .sdkNotAvailable:              return 20005
        case .cannotOpenPaymentApp:         return 20006
        case .missingParameter:             return 20007
        case .networkError:                 return 20008
        case .unsupportedPaymentType:       return 20009
        case .invalidParameters:            return 20010
        case .productNotFound:              return 20011
        case .unknownError:                 return 20012
        case .other:                        return 20013
        case .processorNotFound:            return 20014
        case .receiptNotFound:              return 20015
        case .storeKitError:                return 20016
        case .verifyError:                    return 20017
        }
    }
    
    /// 获取中文错误描述
    public var localizedDescription: String {
        switch self {
        case .purchaseInProgress:
            return "支付正在进行中，请等待完成"
        case .purchaseUserCancelled:
            return "用户取消了支付"
        case .transactionVerificationFailed:
            return "交易验证失败，请重试"
        case .sdkNotIntegrated(let sdk):
            return "\(sdk)未集成，请检查配置"
        case .sdkNotAvailable:
            return "支付SDK不可用，请检查配置"
        case .cannotOpenPaymentApp:
            return "无法打开支付应用，请确认已安装相关应用"
        case .missingParameter(let param):
            return "缺少参数: \(param)"
        case .networkError:
            return "网络错误，请检查网络连接"
        case .unsupportedPaymentType:
            return "不支持的支付类型"
        case .invalidParameters:
            return "无效的支付参数"
        case .productNotFound:
            return "未找到商品信息"
        case .unknownError:
            return "未知错误"
        case .other(let message):
            return "支付错误: \(message)"
        case .processorNotFound:
            return "未找到支付处理器"
        case .receiptNotFound:
            return "未找到购买收据"
        case .storeKitError(let error):
            return "应用内购买错误: \(error.localizedDescription)"
        case .verifyError(let error):
            return "服务器验证失败: \(error.localizedDescription)"
        }
    }
    
    /// 获取错误信息字典
    public var errorInfo: [String: Any] {
        var info: [String: Any] = [
            "code": self.code,
            "message": self.localizedDescription
        ]
        
        switch self {
        case .sdkNotIntegrated(let sdk):
            info["sdk"] = sdk
        case .missingParameter(let param):
            info["parameter"] = param
        case .other(let message):
            info["detail"] = message
        case .storeKitError(let error):
            info["originalError"] = (error as NSError).localizedDescription
            info["originalErrorCode"] = (error as NSError).code
        case .verifyError(let error):
            info["originalError"] = (error as NSError).localizedDescription
            info["originalErrorCode"] = (error as NSError).code
        default:
            break
        }
        
        return info
    }
    
    // 实现Equatable协议
    public static func == (lhs: YLPaymentError, rhs: YLPaymentError) -> Bool {
        switch (lhs, rhs) {
        case (.purchaseInProgress, .purchaseInProgress),
             (.purchaseUserCancelled, .purchaseUserCancelled),
             (.transactionVerificationFailed, .transactionVerificationFailed),
             (.sdkNotAvailable, .sdkNotAvailable),
             (.cannotOpenPaymentApp, .cannotOpenPaymentApp),
             (.networkError, .networkError),
             (.unsupportedPaymentType, .unsupportedPaymentType),
             (.invalidParameters, .invalidParameters),
             (.productNotFound, .productNotFound),
             (.processorNotFound, .processorNotFound),
             (.receiptNotFound, .receiptNotFound),
             (.unknownError, .unknownError):
            return true
        case (.sdkNotIntegrated(let a), .sdkNotIntegrated(let b)):
            return a == b
        case (.missingParameter(let a), .missingParameter(let b)):
            return a == b
        case (.other(let a), .other(let b)):
            return a == b
        case (.storeKitError(let a), .storeKitError(let b)):
            return (a as NSError) == (b as NSError)
        default:
            return false
        }
    }
}

/// 支付结果类型
public enum YLPaymentResult {
    case success(YLPaymentResultData)  // 支付成功，携带结构化数据
    case failure(YLPaymentError) // 支付失败
    case cancel                  // 支付取消
}

/// 支付结果数据对象
public struct YLPaymentResultData {
    /// 订单ID
    public let orderId: String
    
    /// 交易ID
    public let transactionId: String
    
    /// 产品ID
    public let productId: String?
    
    /// 交易日期
    public let transactionDate: Date
    
    /// 原始交易ID (用于续订)
    public let originalTransactionId: String?
    
    /// 原始信息
    public let transactionInfo: YLTransactionInfo?
    
    /// 原始信息
    public let rawInfo: Any
    
    /// 初始化
    public init(orderId: String, transactionId: String, productId: String? = nil,
                transactionDate: Date = Date(), originalTransactionId: String? = nil,
                transactionInfo: YLTransactionInfo? = nil,
                rawInfo: Any = [:]) {
        self.orderId = orderId
        self.transactionId = transactionId
        self.productId = productId
        self.transactionDate = transactionDate
        self.originalTransactionId = originalTransactionId
        self.rawInfo = rawInfo
        self.transactionInfo = transactionInfo
    }
}

/// 支付配置
public struct YLPaymentConfig {
    // 通用配置
    public var appId: String?
    public var universalLink: String?
    public var urlScheme: String?
    
    // 微信特有配置
    public var wxAppId: String?
    public var wxUniversalLink: String?
    
    // 支付宝特有配置
    public var alipayScheme: String?
    
    // 内购配置
    public var iapVersion: YLIAPVersion
    
    // 订单号转换协议
    public var orderIdConverter: YLOrderIDConverter?
    
    public init(
        appId: String? = nil,
        universalLink: String? = nil,
        urlScheme: String? = nil,
        wxAppId: String? = nil,
        wxUniversalLink: String? = nil,
        alipayScheme: String? = nil,
        iapVersion: YLIAPVersion = .auto,
        orderIdConverter: YLOrderIDConverter? = nil
    ) {
        self.appId = appId
        self.universalLink = universalLink
        self.urlScheme = urlScheme
        self.wxAppId = wxAppId ?? appId
        self.wxUniversalLink = wxUniversalLink ?? universalLink
        self.alipayScheme = alipayScheme ?? urlScheme
        self.iapVersion = iapVersion
        self.orderIdConverter = orderIdConverter
    }
}

/// 支付处理器协议
public protocol YLPaymentProcessor {
    /// 支付类型
    var paymentType: YLPaymentType { get }
    
    /// 是否可用
    var isAvailable: Bool { get }
    
    /// 设置支付处理器
    func setup(config: YLPaymentConfig)
    
    /// 处理支付（使用YLPaymentParams）
    func handlePayment(params: YLPaymentParams, completion: @escaping (YLPaymentResult) -> Void)
    
    /// 能否处理URL
    func canHandleURL(_ url: URL) -> Bool
    
    /// 处理URL回调
    func handleURL(_ url: URL) -> Bool
}


/// 支付模型
public struct YLPaymentModel {
    /// 支付类型
    public let paymentType: YLPaymentType
    
    /// 支付参数
    public let params: YLPaymentParams
    
    /// 额外参数
    public let extraParams: [String: Any]?
    
    /// 初始化支付模型
    public init(paymentType: YLPaymentType, params: YLPaymentParams, extraParams: [String: Any]? = nil) {
        self.paymentType = paymentType
        self.params = params
        self.extraParams = extraParams
    }
}

// MARK: - 支付参数协议定义

/// 支付参数协议
public protocol YLPaymentParams {
    /// 订单ID
    var orderId: String { get }
}

/// 内购版本
public enum YLIAPVersion {
    /// 自动选择版本（根据系统自动选择合适的API版本）
    case auto
    /// 强制使用StoreKit 1
    case v1
    /// 强制使用StoreKit 2
    case v2
}

/// 内购支付参数
public struct YLIAPParams: YLPaymentParams {
    /// 产品ID
    public let productId: String
    /// 订单ID
    public let orderId: String

    
    /// 初始化方法
    /// - Parameters:
    ///   - productId: 产品ID
    ///   - orderId: 订单ID
    ///   - version: 内购版本，默认为自动选择（已弃用，请在YLPaymentManager初始化时指定）
    public init(productId: String, orderId: String) {
        self.productId = productId
        self.orderId = orderId
    }
}

/// 支付宝支付参数
public struct YLAlipayParams: YLPaymentParams {
    /// 订单ID
    public let orderId: String
    
    /// 金额
    public let amount: Double?
    
    /// 商品标题
    public let subject: String?
    
    /// 商品详情
    public let body: String?
    
    /// 通知URL
    public let notifyUrl: String?
    
    /// 返回URL
    public let returnUrl: String?
    
    /// 完整的支付参数字符串（接口返回的已拼接好的参数）
    public let paymentString: String?
    
    /// 使用分离参数初始化
    public init(orderId: String, amount: Double, subject: String, body: String? = nil,
                notifyUrl: String? = nil, returnUrl: String? = nil) {
        self.orderId = orderId
        self.amount = amount
        self.subject = subject
        self.body = body
        self.notifyUrl = notifyUrl
        self.returnUrl = returnUrl
        self.paymentString = nil
    }
    
    /// 使用完整支付参数初始化
    public init(orderId: String, paymentString: String) {
        self.orderId = orderId
        self.paymentString = paymentString
        self.amount = nil
        self.subject = nil
        self.body = nil
        self.notifyUrl = nil
        self.returnUrl = nil
    }
}

/// 微信支付参数
public struct YLWechatParams: YLPaymentParams {
    /// 订单ID
    public let orderId: String
    
    /// 金额
    public let amount: Double
    
    /// 商品描述
    public let description: String
    
    /// 用户OpenID
    public let openId: String?
    
    /// 以下为微信支付必需参数
    /// 应用ID
    public let appId: String?
    
    /// 商户ID
    public let partnerId: String?
    
    /// 预支付ID
    public let prepayId: String?
    
    /// 随机字符串
    public let nonceStr: String?
    
    /// 时间戳
    public let timeStamp: String?
    
    /// 包名
    public let package: String?
    
    /// 签名
    public let sign: String?
    
    /// 基础初始化方法（不包含微信支付参数，仅用于生成预支付订单）
    public init(orderId: String, amount: Double, description: String, openId: String? = nil) {
        self.orderId = orderId
        self.amount = amount
        self.description = description
        self.openId = openId
        self.appId = nil
        self.partnerId = nil
        self.prepayId = nil
        self.nonceStr = nil
        self.timeStamp = nil
        self.package = nil
        self.sign = nil
    }
    
    /// 完整初始化方法（包含微信支付所需的所有参数）
    public init(orderId: String, amount: Double, description: String, openId: String? = nil,
                appId: String, partnerId: String, prepayId: String, nonceStr: String,
                timeStamp: String, package: String, sign: String) {
        self.orderId = orderId
        self.amount = amount
        self.description = description
        self.openId = openId
        self.appId = appId
        self.partnerId = partnerId
        self.prepayId = prepayId
        self.nonceStr = nonceStr
        self.timeStamp = timeStamp
        self.package = package
        self.sign = sign
    }
}

// MARK: - NSError 支付错误扩展

public extension NSError {
    /// 支付错误域
    static let ylPaymentErrorDomain = "com.ylpayment.error"
    
    /// 支付错误码
    enum YLPaymentErrorCode: Int {
        case unknown = -1
        case networkError = 1001
        case serverError = 1002
        case userCancelled = 1003
        case invalidParameters = 1004
        case paymentNotSupported = 1005
        case orderVerificationFailed = 1006
        case sdkInitFailed = 1007
        case sdkNotAvailable = 1008
        case insufficientBalance = 1009
        case orderProcessFailed = 1010
    }
    
    /// 创建支付错误
    /// - Parameters:
    ///   - code: 错误码
    ///   - message: 错误信息
    ///   - details: 其他详细信息
    /// - Returns: 支付错误NSError实例
    static func paymentError(code: Int, message: String, details: [String: Any]? = nil) -> NSError {
        var userInfo: [String: Any] = [NSLocalizedDescriptionKey: message]
        
        if let details = details {
            for (key, value) in details {
                userInfo[key] = value
            }
        }
        
        return NSError(domain: ylPaymentErrorDomain, code: code, userInfo: userInfo)
    }
}
